package org.richin.date.util;

import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.TimeZone;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.richin.lang.util.StringUtils;

/*-----------------------------------------------------------
 * Calendar 不能直接new 出来而是要通过Calendar.getInstance()
 -------------------------------------------------------------*/
/**
 * 日期帮助类 z
 * 
 * @author 秦博
 * 
 */
public class DateUtils {

	private static final Log log = LogFactory.getLog(DateUtils.class);
	/**
	 * Number of milliseconds in a standard second.
	 * @since 2.1
	 */
	public static final long MILLIS_PER_SECOND = 1000;
	/**
	 * Number of milliseconds in a standard minute.
	 * @since 2.1
	 */
	public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
	/**
	 * Number of milliseconds in a standard hour.
	 * @since 2.1
	 */
	public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
	/**
	 * Number of milliseconds in a standard day.
	 * @since 2.1
	 */
	public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;

	/**
	 * This is half a month, so this represents whether a date is in the top
	 * or bottom half of the month.
	 */
	public final static int SEMI_MONTH = 1001;

	private static final int[][] fields = { { Calendar.MILLISECOND }, { Calendar.SECOND }, { Calendar.MINUTE },
			{ Calendar.HOUR_OF_DAY, Calendar.HOUR }, { Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.AM_PM
			/* Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK, Calendar.DAY_OF_WEEK_IN_MONTH */
			}, { Calendar.MONTH, DateUtils.SEMI_MONTH }, { Calendar.YEAR }, { Calendar.ERA } };

	/**
	 * A week range, starting on Sunday.
	 */
	public final static int RANGE_WEEK_SUNDAY = 1;

	/**
	 * A week range, starting on Monday.
	 */
	public final static int RANGE_WEEK_MONDAY = 2;

	/**
	 * A week range, starting on the day focused.
	 */
	public final static int RANGE_WEEK_RELATIVE = 3;

	/**
	 * A week range, centered around the day focused.
	 */
	public final static int RANGE_WEEK_CENTER = 4;

	/**
	 * A month range, the week starting on Sunday.
	 */
	public final static int RANGE_MONTH_SUNDAY = 5;

	/**
	 * A month range, the week starting on Monday.
	 */
	public final static int RANGE_MONTH_MONDAY = 6;

	/**
	 * 返回跨两个指定日期的日期和时间边界数
	 * @param datepart
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static int DateDiff(String datepart, Date startDate, Date endDate) {

		return 0;

	}

	/**
	* <p>Checks if two date objects are on the same day ignoring time.</p>
	*
	* <p>28 Mar 2002 13:45 and 28 Mar 2002 06:01 would return true.
	* 28 Mar 2002 13:45 and 12 Mar 2002 13:45 would return false.
	* </p>
	* 
	* @param date1  the first date, not altered, not null
	* @param date2  the second date, not altered, not null
	* @return true if they represent the same day
	* @throws IllegalArgumentException if either date is <code>null</code>
	* @since 2.1
	*/
	public static boolean isSameDay(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar cal1 = Calendar.getInstance();
		cal1.clear();
		cal1.setTime(date1);
		Calendar cal2 = Calendar.getInstance();
		cal2.clear();
		cal2.setTime(date2);
		return isSameDay(cal1, cal2);
	}

	/**
	 * 14 * 取得某天相加(减)後的那一天 15 * 16 *
	 * 
	 * @param date
	 *            17 *
	 * @param num(可正可负)
	 *            18 *
	 * @return 19
	 */
	public static Date getAnotherDate(Date date, int num) {
		Calendar c = Calendar.getInstance();
		c.clear();
		c.setTime(date);
		c.add(Calendar.DAY_OF_YEAR, num);
		return c.getTime();
	}

	/**
	 * <p>Checks if two calendar objects are on the same day ignoring time.</p>
	 *
	 * <p>28 Mar 2002 13:45 and 28 Mar 2002 06:01 would return true.
	 * 28 Mar 2002 13:45 and 12 Mar 2002 13:45 would return false.
	 * </p>
	 * 
	 * @param cal1  the first calendar, not altered, not null
	 * @param cal2  the second calendar, not altered, not null
	 * @return true if they represent the same day
	 * @throws IllegalArgumentException if either calendar is <code>null</code>
	 * @since 2.1
	 */
	public static boolean isSameDay(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1
				.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
	}

	/**
	 * <p>Checks if two date objects represent the same instant in time.</p>
	 *
	 * <p>This method compares the long millisecond time of the two objects.</p>
	 * 
	 * @param date1  the first date, not altered, not null
	 * @param date2  the second date, not altered, not null
	 * @return true if they represent the same millisecond instant
	 * @throws IllegalArgumentException if either date is <code>null</code>
	 * @since 2.1
	 */
	public static boolean isSameInstant(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		return date1.getTime() == date2.getTime();
	}

	/**
	 * <p>Checks if two calendar objects represent the same instant in time.</p>
	 *
	 * <p>This method compares the long millisecond time of the two objects.</p>
	 * 
	 * @param cal1  the first calendar, not altered, not null
	 * @param cal2  the second calendar, not altered, not null
	 * @return true if they represent the same millisecond instant
	 * @throws IllegalArgumentException if either date is <code>null</code>
	 * @since 2.1
	 */
	public static boolean isSameInstant(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		return cal1.getTime().getTime() == cal2.getTime().getTime();
	}

	/**
	 * <p>Checks if two calendar objects represent the same local time.</p>
	 *
	 * <p>This method compares the values of the fields of the two objects.
	 * In addition, both calendars must be the same of the same type.</p>
	 * 
	 * @param cal1  the first calendar, not altered, not null
	 * @param cal2  the second calendar, not altered, not null
	 * @return true if they represent the same millisecond instant
	 * @throws IllegalArgumentException if either date is <code>null</code>
	 * @since 2.1
	 */
	public static boolean isSameLocalTime(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		return (cal1.get(Calendar.MILLISECOND) == cal2.get(Calendar.MILLISECOND)
				&& cal1.get(Calendar.SECOND) == cal2.get(Calendar.SECOND)
				&& cal1.get(Calendar.MINUTE) == cal2.get(Calendar.MINUTE)
				&& cal1.get(Calendar.HOUR) == cal2.get(Calendar.HOUR)
				&& cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR)
				&& cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
				&& cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && cal1.getClass() == cal2.getClass());
	}

	//-----------------------------------------------------------------------
	/**
	 * <p>Parses a string representing a date by trying a variety of different parsers.</p>
	 * 
	 * <p>The parse will try each parse pattern in turn.
	 * A parse is only deemed sucessful if it parses the whole of the input string.
	 * If no parse patterns match, a ParseException is thrown.</p>
	 * 
	 * @param str  the date to parse, not null
	 * @param parsePatterns  the date format patterns to use, see SimpleDateFormat, not null
	 * @return the parsed date
	 * @throws IllegalArgumentException if the date string or pattern array is null
	 * @throws ParseException if none of the date patterns were suitable
	 */
	public static Date parseDate(String str, String[] parsePatterns) throws ParseException {
		if (str == null || parsePatterns == null) {
			throw new IllegalArgumentException("Date and Patterns must not be null");
		}

		SimpleDateFormat parser = null;
		ParsePosition pos = new ParsePosition(0);
		for (int i = 0; i < parsePatterns.length; i++) {
			if (i == 0) {
				parser = new SimpleDateFormat(parsePatterns[0]);
			} else {
				parser.applyPattern(parsePatterns[i]);
			}
			pos.setIndex(0);
			Date date = parser.parse(str, pos);
			if (date != null && pos.getIndex() == str.length()) {
				return date;
			}
		}
		throw new ParseException("Unable to parse the date: " + str, -1);
	}

	//-----------------------------------------------------------------------
	/**
	 * Adds a number of years to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount  the amount to add, may be negative
	 * @return the new date object with the amount added
	 * @throws IllegalArgumentException if the date is null
	 */
	public static Date addYears(Date date, int amount) {
		return add(date, Calendar.YEAR, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Adds a number of months to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount  the amount to add, may be negative
	 * @return the new date object with the amount added
	 * @throws IllegalArgumentException if the date is null
	 */
	public static Date addMonths(Date date, int amount) {
		return add(date, Calendar.MONTH, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Adds a number of weeks to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount  the amount to add, may be negative
	 * @return the new date object with the amount added
	 * @throws IllegalArgumentException if the date is null
	 */
	public static Date addWeeks(Date date, int amount) {
		return add(date, Calendar.WEEK_OF_YEAR, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Adds a number of days to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount  the amount to add, may be negative
	 * @return the new date object with the amount added
	 * @throws IllegalArgumentException if the date is null
	 */
	public static Date addDays(Date date, int amount) {
		return add(date, Calendar.DAY_OF_MONTH, amount);
	}
	/**
	 * 比较给与的时间date与今天的时间相差天数是否小于day
	 * @param date
	 * @param date2
	 * @return
	 */
	public static boolean compareTime(String date, int day) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date1;
		try {
			date1 = dateFormat.parse(date);
		} catch (ParseException e) {
			return false;//返回一个很大的数
		}
		Calendar c1 = Calendar.getInstance();
		c1.clear();
		c1.setTime(date1);
		int day1 = c1.get(Calendar.DAY_OF_YEAR);
		Calendar c2 = Calendar.getInstance();
		c2.clear();
		c2.setTime(new Date());
		int day2 = c2.get(Calendar.DAY_OF_YEAR);
		return Math.abs(day2 - day1)<day;
		
	}
	//-----------------------------------------------------------------------
	/**
	 * Adds a number of hours to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount  the amount to add, may be negative
	 * @return the new date object with the amount added
	 * @throws IllegalArgumentException if the date is null
	 */
	public static Date addHours(Date date, int amount) {
		return add(date, Calendar.HOUR_OF_DAY, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Adds a number of minutes to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount  the amount to add, may be negative
	 * @return the new date object with the amount added
	 * @throws IllegalArgumentException if the date is null
	 */
	public static Date addMinutes(Date date, int amount) {
		return add(date, Calendar.MINUTE, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Adds a number of seconds to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount  the amount to add, may be negative
	 * @return the new date object with the amount added
	 * @throws IllegalArgumentException if the date is null
	 */
	public static Date addSeconds(Date date, int amount) {
		return add(date, Calendar.SECOND, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Adds a number of milliseconds to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount  the amount to add, may be negative
	 * @return the new date object with the amount added
	 * @throws IllegalArgumentException if the date is null
	 */
	public static Date addMilliseconds(Date date, int amount) {
		return add(date, Calendar.MILLISECOND, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Adds to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param calendarField  the calendar field to add to
	 * @param amount  the amount to add, may be negative
	 * @return the new date object with the amount added
	 * @throws IllegalArgumentException if the date is null
	 * 
	 */
	public static Date add(Date date, int calendarField, int amount) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(calendarField, amount);
		return c.getTime();
	}

	//-----------------------------------------------------------------------
	/**
	 * Sets the years field to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount the amount to set
	 * @return a new Date object set with the specified value
	 * @throws IllegalArgumentException if the date is null
	 * @since 2.4
	 */
	public static Date setYears(Date date, int amount) {
		return set(date, Calendar.YEAR, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Sets the months field to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount the amount to set
	 * @return a new Date object set with the specified value
	 * @throws IllegalArgumentException if the date is null
	 * @since 2.4
	 */
	public static Date setMonths(Date date, int amount) {
		return set(date, Calendar.MONTH, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Sets the day of month field to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount the amount to set
	 * @return a new Date object set with the specified value
	 * @throws IllegalArgumentException if the date is null
	 * @since 2.4
	 */
	public static Date setDays(Date date, int amount) {
		return set(date, Calendar.DAY_OF_MONTH, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Sets the hours field to a date returning a new object.  Hours range 
	 * from  0-23.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount the amount to set
	 * @return a new Date object set with the specified value
	 * @throws IllegalArgumentException if the date is null
	 * @since 2.4
	 */
	public static Date setHours(Date date, int amount) {
		return set(date, Calendar.HOUR_OF_DAY, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Sets the minute field to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount the amount to set
	 * @return a new Date object set with the specified value
	 * @throws IllegalArgumentException if the date is null
	 * @since 2.4
	 */
	public static Date setMinutes(Date date, int amount) {
		return set(date, Calendar.MINUTE, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Sets the seconds field to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount the amount to set
	 * @return a new Date object set with the specified value
	 * @throws IllegalArgumentException if the date is null
	 * @since 2.4
	 */
	public static Date setSeconds(Date date, int amount) {
		return set(date, Calendar.SECOND, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Sets the miliseconds field to a date returning a new object.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param amount the amount to set
	 * @return a new Date object set with the specified value
	 * @throws IllegalArgumentException if the date is null
	 * @since 2.4
	 */
	public static Date setMilliseconds(Date date, int amount) {
		return set(date, Calendar.MILLISECOND, amount);
	}

	//-----------------------------------------------------------------------
	/**
	 * Sets the specified field to a date returning a new object.  
	 * This does not use a lenient calendar.
	 * The original date object is unchanged.
	 *
	 * @param date  the date, not null
	 * @param calendarField  the calendar field to set the amount to
	 * @param amount the amount to set
	 * @return a new Date object set with the specified value
	 * @throws IllegalArgumentException if the date is null
	 * @since 2.4
	 */
	private static Date set(Date date, int calendarField, int amount) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		// getInstance() returns a new object, so this method is thread safe.
		Calendar c = Calendar.getInstance();
		c.setLenient(false);
		c.setTime(date);
		c.set(calendarField, amount);
		return c.getTime();
	}

	//-----------------------------------------------------------------------
	/**
	 * <p>Round this date, leaving the field specified as the most
	 * significant field.</p>
	 *
	 * <p>For example, if you had the datetime of 28 Mar 2002
	 * 13:45:01.231, if this was passed with HOUR, it would return
	 * 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
	 * would return 1 April 2002 0:00:00.000.</p>
	 * 
	 * <p>For a date in a timezone that handles the change to daylight
	 * saving time, rounding to Calendar.HOUR_OF_DAY will behave as follows.
	 * Suppose daylight saving time begins at 02:00 on March 30. Rounding a 
	 * date that crosses this time would produce the following values:
	 * <ul>
	 * <li>March 30, 2003 01:10 rounds to March 30, 2003 01:00</li>
	 * <li>March 30, 2003 01:40 rounds to March 30, 2003 03:00</li>
	 * <li>March 30, 2003 02:10 rounds to March 30, 2003 03:00</li>
	 * <li>March 30, 2003 02:40 rounds to March 30, 2003 04:00</li>
	 * </ul>
	 * </p>
	 * 
	 * @param date  the date to work with
	 * @param field  the field from <code>Calendar</code>
	 *  or <code>SEMI_MONTH</code>
	 * @return the rounded date
	 * @throws IllegalArgumentException if the date is <code>null</code>
	 * @throws ArithmeticException if the year is over 280 million
	 */
	public static Date round(Date date, int field) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar gval = Calendar.getInstance();
		gval.setTime(date);
		modify(gval, field, true);
		return gval.getTime();
	}

	/**
	 * <p>Round this date, leaving the field specified as the most
	 * significant field.</p>
	 *
	 * <p>For example, if you had the datetime of 28 Mar 2002
	 * 13:45:01.231, if this was passed with HOUR, it would return
	 * 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
	 * would return 1 April 2002 0:00:00.000.</p>
	 * 
	 * <p>For a date in a timezone that handles the change to daylight
	 * saving time, rounding to Calendar.HOUR_OF_DAY will behave as follows.
	 * Suppose daylight saving time begins at 02:00 on March 30. Rounding a 
	 * date that crosses this time would produce the following values:
	 * <ul>
	 * <li>March 30, 2003 01:10 rounds to March 30, 2003 01:00</li>
	 * <li>March 30, 2003 01:40 rounds to March 30, 2003 03:00</li>
	 * <li>March 30, 2003 02:10 rounds to March 30, 2003 03:00</li>
	 * <li>March 30, 2003 02:40 rounds to March 30, 2003 04:00</li>
	 * </ul>
	 * </p>
	 * 
	 * @param date  the date to work with
	 * @param field  the field from <code>Calendar</code>
	 *  or <code>SEMI_MONTH</code>
	 * @return the rounded date (a different object)
	 * @throws IllegalArgumentException if the date is <code>null</code>
	 * @throws ArithmeticException if the year is over 280 million
	 */
	public static Calendar round(Calendar date, int field) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar rounded = (Calendar) date.clone();
		modify(rounded, field, true);
		return rounded;
	}

	/**
	 * <p>Round this date, leaving the field specified as the most
	 * significant field.</p>
	 *
	 * <p>For example, if you had the datetime of 28 Mar 2002
	 * 13:45:01.231, if this was passed with HOUR, it would return
	 * 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
	 * would return 1 April 2002 0:00:00.000.</p>
	 * 
	 * <p>For a date in a timezone that handles the change to daylight
	 * saving time, rounding to Calendar.HOUR_OF_DAY will behave as follows.
	 * Suppose daylight saving time begins at 02:00 on March 30. Rounding a 
	 * date that crosses this time would produce the following values:
	 * <ul>
	 * <li>March 30, 2003 01:10 rounds to March 30, 2003 01:00</li>
	 * <li>March 30, 2003 01:40 rounds to March 30, 2003 03:00</li>
	 * <li>March 30, 2003 02:10 rounds to March 30, 2003 03:00</li>
	 * <li>March 30, 2003 02:40 rounds to March 30, 2003 04:00</li>
	 * </ul>
	 * </p>
	 * 
	 * @param date  the date to work with, either Date or Calendar
	 * @param field  the field from <code>Calendar</code>
	 *  or <code>SEMI_MONTH</code>
	 * @return the rounded date
	 * @throws IllegalArgumentException if the date is <code>null</code>
	 * @throws ClassCastException if the object type is not a <code>Date</code>
	 *  or <code>Calendar</code>
	 * @throws ArithmeticException if the year is over 280 million
	 */
	public static Date round(Object date, int field) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		if (date instanceof Date) {
			return round((Date) date, field);
		} else if (date instanceof Calendar) {
			return round((Calendar) date, field).getTime();
		} else {
			throw new ClassCastException("Could not round " + date);
		}
	}

	//-----------------------------------------------------------------------
	/**
	 * <p>Truncate this date, leaving the field specified as the most
	 * significant field.</p>
	 *
	 * <p>For example, if you had the datetime of 28 Mar 2002
	 * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
	 * 2002 13:00:00.000.  If this was passed with MONTH, it would
	 * return 1 Mar 2002 0:00:00.000.</p>
	 * 
	 * @param date  the date to work with
	 * @param field  the field from <code>Calendar</code>
	 *  or <code>SEMI_MONTH</code>
	 * @return the rounded date
	 * @throws IllegalArgumentException if the date is <code>null</code>
	 * @throws ArithmeticException if the year is over 280 million
	 */
	public static Date truncate(Date date, int field) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar gval = Calendar.getInstance();
		gval.setTime(date);
		modify(gval, field, false);
		return gval.getTime();
	}

	/**
	 * <p>Truncate this date, leaving the field specified as the most
	 * significant field.</p>
	 *
	 * <p>For example, if you had the datetime of 28 Mar 2002
	 * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
	 * 2002 13:00:00.000.  If this was passed with MONTH, it would
	 * return 1 Mar 2002 0:00:00.000.</p>
	 * 
	 * @param date  the date to work with
	 * @param field  the field from <code>Calendar</code>
	 *  or <code>SEMI_MONTH</code>
	 * @return the rounded date (a different object)
	 * @throws IllegalArgumentException if the date is <code>null</code>
	 * @throws ArithmeticException if the year is over 280 million
	 */
	public static Calendar truncate(Calendar date, int field) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar truncated = (Calendar) date.clone();
		modify(truncated, field, false);
		return truncated;
	}

	/**
	 * <p>Truncate this date, leaving the field specified as the most
	 * significant field.</p>
	 *
	 * <p>For example, if you had the datetime of 28 Mar 2002
	 * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
	 * 2002 13:00:00.000.  If this was passed with MONTH, it would
	 * return 1 Mar 2002 0:00:00.000.</p>
	 * 
	 * @param date  the date to work with, either <code>Date</code>
	 *  or <code>Calendar</code>
	 * @param field  the field from <code>Calendar</code>
	 *  or <code>SEMI_MONTH</code>
	 * @return the rounded date
	 * @throws IllegalArgumentException if the date
	 *  is <code>null</code>
	 * @throws ClassCastException if the object type is not a
	 *  <code>Date</code> or <code>Calendar</code>
	 * @throws ArithmeticException if the year is over 280 million
	 */
	public static Date truncate(Object date, int field) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		if (date instanceof Date) {
			return truncate((Date) date, field);
		} else if (date instanceof Calendar) {
			return truncate((Calendar) date, field).getTime();
		} else {
			throw new ClassCastException("Could not truncate " + date);
		}
	}

	//-----------------------------------------------------------------------
	/**
	 * <p>Internal calculation method.</p>
	 * 
	 * @param val  the calendar
	 * @param field  the field constant
	 * @param round  true to round, false to truncate
	 * @throws ArithmeticException if the year is over 280 million
	 */
	private static void modify(Calendar val, int field, boolean round) {
		if (val.get(Calendar.YEAR) > 280000000) {
			throw new ArithmeticException("Calendar value too large for accurate calculations");
		}

		if (field == Calendar.MILLISECOND) {
			return;
		}

		// ----------------- Fix for LANG-59 ---------------------- START ---------------
		// see http://issues.apache.org/jira/browse/LANG-59
		//
		// Manually truncate milliseconds, seconds and minutes, rather than using
		// Calendar methods.

		Date date = val.getTime();
		long time = date.getTime();
		boolean done = false;

		// truncate milliseconds
		int millisecs = val.get(Calendar.MILLISECOND);
		if (!round || millisecs < 500) {
			time = time - millisecs;
		}
		if (field == Calendar.SECOND) {
			done = true;
		}

		// truncate seconds
		int seconds = val.get(Calendar.SECOND);
		if (!done && (!round || seconds < 30)) {
			time = time - (seconds * 1000L);
		}
		if (field == Calendar.MINUTE) {
			done = true;
		}

		// truncate minutes
		int minutes = val.get(Calendar.MINUTE);
		if (!done && (!round || minutes < 30)) {
			time = time - (minutes * 60000L);
		}

		// reset time
		if (date.getTime() != time) {
			date.setTime(time);
			val.setTime(date);
		}
		// ----------------- Fix for LANG-59 ----------------------- END ----------------

		boolean roundUp = false;
		for (int i = 0; i < fields.length; i++) {
			for (int j = 0; j < fields[i].length; j++) {
				if (fields[i][j] == field) {
					//This is our field... we stop looping
					if (round && roundUp) {
						if (field == DateUtils.SEMI_MONTH) {
							//This is a special case that's hard to generalize
							//If the date is 1, we round up to 16, otherwise
							//  we subtract 15 days and add 1 month
							if (val.get(Calendar.DATE) == 1) {
								val.add(Calendar.DATE, 15);
							} else {
								val.add(Calendar.DATE, -15);
								val.add(Calendar.MONTH, 1);
							}
						} else {
							//We need at add one to this field since the
							//  last number causes us to round up
							val.add(fields[i][0], 1);
						}
					}
					return;
				}
			}
			//We have various fields that are not easy roundings
			int offset = 0;
			boolean offsetSet = false;
			//These are special types of fields that require different rounding rules
			switch (field) {
			case DateUtils.SEMI_MONTH:
				if (fields[i][0] == Calendar.DATE) {
					//If we're going to drop the DATE field's value,
					//  we want to do this our own way.
					//We need to subtrace 1 since the date has a minimum of 1
					offset = val.get(Calendar.DATE) - 1;
					//If we're above 15 days adjustment, that means we're in the
					//  bottom half of the month and should stay accordingly.
					if (offset >= 15) {
						offset -= 15;
					}
					//Record whether we're in the top or bottom half of that range
					roundUp = offset > 7;
					offsetSet = true;
				}
				break;
			case Calendar.AM_PM:
				if (fields[i][0] == Calendar.HOUR_OF_DAY) {
					//If we're going to drop the HOUR field's value,
					//  we want to do this our own way.
					offset = val.get(Calendar.HOUR_OF_DAY);
					if (offset >= 12) {
						offset -= 12;
					}
					roundUp = offset > 6;
					offsetSet = true;
				}
				break;
			}
			if (!offsetSet) {
				int min = val.getActualMinimum(fields[i][0]);
				int max = val.getActualMaximum(fields[i][0]);
				//Calculate the offset from the minimum allowed value
				offset = val.get(fields[i][0]) - min;
				//Set roundUp if this is more than half way between the minimum and maximum
				roundUp = offset > ((max - min) / 2);
			}
			//We need to remove this field
			if (offset != 0) {
				val.set(fields[i][0], val.get(fields[i][0]) - offset);
			}
		}
		throw new IllegalArgumentException("The field " + field + " is not supported");

	}

	//-----------------------------------------------------------------------
	/**
	 * <p>This constructs an <code>Iterator</code> over each day in a date
	 * range defined by a focus date and range style.</p>
	 *
	 * <p>For instance, passing Thursday, July 4, 2002 and a
	 * <code>RANGE_MONTH_SUNDAY</code> will return an <code>Iterator</code>
	 * that starts with Sunday, June 30, 2002 and ends with Saturday, August 3,
	 * 2002, returning a Calendar instance for each intermediate day.</p>
	 *
	 * <p>This method provides an iterator that returns Calendar objects.
	 * The days are progressed using {@link Calendar#add(int, int)}.</p>
	 *
	 * @param focus  the date to work with, not null
	 * @param rangeStyle  the style constant to use. Must be one of
	 * {@link DateUtils#RANGE_MONTH_SUNDAY}, 
	 * {@link DateUtils#RANGE_MONTH_MONDAY},
	 * {@link DateUtils#RANGE_WEEK_SUNDAY},
	 * {@link DateUtils#RANGE_WEEK_MONDAY},
	 * {@link DateUtils#RANGE_WEEK_RELATIVE},
	 * {@link DateUtils#RANGE_WEEK_CENTER}
	 * @return the date iterator, which always returns Calendar instances
	 * @throws IllegalArgumentException if the date is <code>null</code>
	 * @throws IllegalArgumentException if the rangeStyle is invalid
	 */
	public static Iterator iterator(Date focus, int rangeStyle) {
		if (focus == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar gval = Calendar.getInstance();
		gval.setTime(focus);
		return iterator(gval, rangeStyle);
	}

	/**
	 * <p>This constructs an <code>Iterator</code> over each day in a date
	 * range defined by a focus date and range style.</p>
	 *
	 * <p>For instance, passing Thursday, July 4, 2002 and a
	 * <code>RANGE_MONTH_SUNDAY</code> will return an <code>Iterator</code>
	 * that starts with Sunday, June 30, 2002 and ends with Saturday, August 3,
	 * 2002, returning a Calendar instance for each intermediate day.</p>
	 *
	 * <p>This method provides an iterator that returns Calendar objects.
	 * The days are progressed using {@link Calendar#add(int, int)}.</p>
	 *
	 * @param focus  the date to work with
	 * @param rangeStyle  the style constant to use. Must be one of
	 * {@link DateUtils#RANGE_MONTH_SUNDAY}, 
	 * {@link DateUtils#RANGE_MONTH_MONDAY},
	 * {@link DateUtils#RANGE_WEEK_SUNDAY},
	 * {@link DateUtils#RANGE_WEEK_MONDAY},
	 * {@link DateUtils#RANGE_WEEK_RELATIVE},
	 * {@link DateUtils#RANGE_WEEK_CENTER}
	 * @return the date iterator
	 * @throws IllegalArgumentException if the date is <code>null</code>
	 * @throws IllegalArgumentException if the rangeStyle is invalid
	 */
	public static Iterator iterator(Calendar focus, int rangeStyle) {
		if (focus == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar start = null;
		Calendar end = null;
		int startCutoff = Calendar.SUNDAY;
		int endCutoff = Calendar.SATURDAY;
		switch (rangeStyle) {
		case RANGE_MONTH_SUNDAY:
		case RANGE_MONTH_MONDAY:
			//Set start to the first of the month
			start = truncate(focus, Calendar.MONTH);
			//Set end to the last of the month
			end = (Calendar) start.clone();
			end.add(Calendar.MONTH, 1);
			end.add(Calendar.DATE, -1);
			//Loop start back to the previous sunday or monday
			if (rangeStyle == RANGE_MONTH_MONDAY) {
				startCutoff = Calendar.MONDAY;
				endCutoff = Calendar.SUNDAY;
			}
			break;
		case RANGE_WEEK_SUNDAY:
		case RANGE_WEEK_MONDAY:
		case RANGE_WEEK_RELATIVE:
		case RANGE_WEEK_CENTER:
			//Set start and end to the current date
			start = truncate(focus, Calendar.DATE);
			end = truncate(focus, Calendar.DATE);
			switch (rangeStyle) {
			case RANGE_WEEK_SUNDAY:
				//already set by default
				break;
			case RANGE_WEEK_MONDAY:
				startCutoff = Calendar.MONDAY;
				endCutoff = Calendar.SUNDAY;
				break;
			case RANGE_WEEK_RELATIVE:
				startCutoff = focus.get(Calendar.DAY_OF_WEEK);
				endCutoff = startCutoff - 1;
				break;
			case RANGE_WEEK_CENTER:
				startCutoff = focus.get(Calendar.DAY_OF_WEEK) - 3;
				endCutoff = focus.get(Calendar.DAY_OF_WEEK) + 3;
				break;
			}
			break;
		default:
			throw new IllegalArgumentException("The range style " + rangeStyle + " is not valid.");
		}
		if (startCutoff < Calendar.SUNDAY) {
			startCutoff += 7;
		}
		if (startCutoff > Calendar.SATURDAY) {
			startCutoff -= 7;
		}
		if (endCutoff < Calendar.SUNDAY) {
			endCutoff += 7;
		}
		if (endCutoff > Calendar.SATURDAY) {
			endCutoff -= 7;
		}
		while (start.get(Calendar.DAY_OF_WEEK) != startCutoff) {
			start.add(Calendar.DATE, -1);
		}
		while (end.get(Calendar.DAY_OF_WEEK) != endCutoff) {
			end.add(Calendar.DATE, 1);
		}
		return new DateIterator(start, end);
	}

	/**
	 * <p>This constructs an <code>Iterator</code> over each day in a date
	 * range defined by a focus date and range style.</p>
	 *
	 * <p>For instance, passing Thursday, July 4, 2002 and a
	 * <code>RANGE_MONTH_SUNDAY</code> will return an <code>Iterator</code>
	 * that starts with Sunday, June 30, 2002 and ends with Saturday, August 3,
	 * 2002, returning a Calendar instance for each intermediate day.</p>
	 *
	 * @param focus  the date to work with, either
	 *  <code>Date</code> or <code>Calendar</code>
	 * @param rangeStyle  the style constant to use. Must be one of the range
	 * styles listed for the {@link #iterator(Calendar, int)} method.
	 * @return the date iterator
	 * @throws IllegalArgumentException if the date
	 *  is <code>null</code>
	 * @throws ClassCastException if the object type is
	 *  not a <code>Date</code> or <code>Calendar</code>
	 */
	public static Iterator iterator(Object focus, int rangeStyle) {
		if (focus == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		if (focus instanceof Date) {
			return iterator((Date) focus, rangeStyle);
		} else if (focus instanceof Calendar) {
			return iterator((Calendar) focus, rangeStyle);
		} else {
			throw new ClassCastException("Could not iterate based on " + focus);
		}
	}

	/**
	 * <p>Returns the number of milliseconds within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p>
	 * 
	 * <p>Asking the milliseconds of any date will only return the number of milliseconds
	 * of the current second (resulting in a number between 0 and 999). This 
	 * method will retrieve the number of milliseconds for any fragment. 
	 * For example, if you want to calculate the number of milliseconds past today, 
	 * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will
	 * be all milliseconds of the past hour(s), minutes(s) and second(s).</p>
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a SECOND field will return 0.</p> 
	 * 
	 * <p>
	 * <ul>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.SECOND as fragment will return 538</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.SECOND as fragment will return 538</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10538 (10*1000 + 538)</li>
	 *  <li>January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in milliseconds)</li>
	 * </ul>
	 * </p>
	 * 
	 * @param date the date to work with, not null
	 * @param fragment the Calendar field part of date to calculate 
	 * @return number of milliseconds within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInMilliseconds(Date date, int fragment) {
		return getFragment(date, fragment, Calendar.MILLISECOND);
	}

	/**
	 * <p>Returns the number of seconds within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p> 
	 * 
	 * <p>Asking the seconds of any date will only return the number of seconds
	 * of the current minute (resulting in a number between 0 and 59). This 
	 * method will retrieve the number of seconds for any fragment. 
	 * For example, if you want to calculate the number of seconds past today, 
	 * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will
	 * be all seconds of the past hour(s) and minutes(s).</p> 
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a SECOND field will return 0.</p> 
	 * 
	 * <p>
	 * <ul>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10
	 *   (equivalent to deprecated date.getSeconds())</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10
	 *   (equivalent to deprecated date.getSeconds())</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 26110
	 *   (7*3600 + 15*60 + 10)</li>
	 *  <li>January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in seconds)</li>
	 * </ul>
	 * </p>
	 * 
	 * @param date the date to work with, not null
	 * @param fragment the Calendar field part of date to calculate 
	 * @return number of seconds within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInSeconds(Date date, int fragment) {
		return getFragment(date, fragment, Calendar.SECOND);
	}

	/**
	 * <p>Returns the number of minutes within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p> 
	 * 
	 * <p>Asking the minutes of any date will only return the number of minutes
	 * of the current hour (resulting in a number between 0 and 59). This 
	 * method will retrieve the number of minutes for any fragment. 
	 * For example, if you want to calculate the number of minutes past this month, 
	 * your fragment is Calendar.MONTH. The result will be all minutes of the 
	 * past day(s) and hour(s).</p> 
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a MINUTE field will return 0.</p> 
	 * 
	 * <p>
	 * <ul>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.HOUR_OF_DAY as fragment will return 15
	 *   (equivalent to deprecated date.getMinutes())</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.HOUR_OF_DAY as fragment will return 15
	 *   (equivalent to deprecated date.getMinutes())</li>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 15</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 435 (7*60 + 15)</li>
	 *  <li>January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in minutes)</li>
	 * </ul>
	 * </p>
	 * 
	 * @param date the date to work with, not null
	 * @param fragment the Calendar field part of date to calculate 
	 * @return number of minutes within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInMinutes(Date date, int fragment) {
		return getFragment(date, fragment, Calendar.MINUTE);
	}

	/**
	 * <p>Returns the number of hours within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p> 
	 * 
	 * <p>Asking the hours of any date will only return the number of hours
	 * of the current day (resulting in a number between 0 and 23). This 
	 * method will retrieve the number of hours for any fragment. 
	 * For example, if you want to calculate the number of hours past this month, 
	 * your fragment is Calendar.MONTH. The result will be all hours of the 
	 * past day(s).</p> 
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a HOUR field will return 0.</p> 
	 * 
	 * <p>
	 * <ul>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 7
	 *   (equivalent to deprecated date.getHours())</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 7
	 *   (equivalent to deprecated date.getHours())</li>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 7</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 127 (5*24 + 7)</li>
	 *  <li>January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in hours)</li>
	 * </ul>
	 * </p>
	 * 
	 * @param date the date to work with, not null
	 * @param fragment the Calendar field part of date to calculate 
	 * @return number of hours within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInHours(Date date, int fragment) {
		return getFragment(date, fragment, Calendar.HOUR_OF_DAY);
	}

	/**
	 * <p>Returns the number of days within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p> 
	 * 
	 * <p>Asking the days of any date will only return the number of days
	 * of the current month (resulting in a number between 1 and 31). This 
	 * method will retrieve the number of days for any fragment. 
	 * For example, if you want to calculate the number of days past this year, 
	 * your fragment is Calendar.YEAR. The result will be all days of the 
	 * past month(s).</p> 
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a DAY field will return 0.</p> 
	 *  
	 * <p>
	 * <ul>
	 *  <li>January 28, 2008 with Calendar.MONTH as fragment will return 28
	 *   (equivalent to deprecated date.getDay())</li>
	 *  <li>February 28, 2008 with Calendar.MONTH as fragment will return 28
	 *   (equivalent to deprecated date.getDay())</li>
	 *  <li>January 28, 2008 with Calendar.YEAR as fragment will return 28</li>
	 *  <li>February 28, 2008 with Calendar.YEAR as fragment will return 59</li>
	 *  <li>January 28, 2008 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in days)</li>
	 * </ul>
	 * </p>
	 * 
	 * @param date the date to work with, not null
	 * @param fragment the Calendar field part of date to calculate 
	 * @return number of days  within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInDays(Date date, int fragment) {
		return getFragment(date, fragment, Calendar.DAY_OF_YEAR);
	}

	/**
	 * <p>Returns the number of milliseconds within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p> 
	 * 
	 * <p>Asking the milliseconds of any date will only return the number of milliseconds
	 * of the current second (resulting in a number between 0 and 999). This 
	 * method will retrieve the number of milliseconds for any fragment. 
	 * For example, if you want to calculate the number of seconds past today, 
	 * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will
	 * be all seconds of the past hour(s), minutes(s) and second(s).</p> 
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a MILLISECOND field will return 0.</p> 
	 * 
	 * <p>
	 * <ul>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.SECOND as fragment will return 538
	 *   (equivalent to calendar.get(Calendar.MILLISECOND))</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.SECOND as fragment will return 538
	 *   (equivalent to calendar.get(Calendar.MILLISECOND))</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10538
	 *   (10*1000 + 538)</li>
	 *  <li>January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in milliseconds)</li>
	 * </ul>
	 * </p>
	 * 
	 * @param calendar the calendar to work with, not null
	 * @param fragment the Calendar field part of calendar to calculate 
	 * @return number of milliseconds within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInMilliseconds(Calendar calendar, int fragment) {
		return getFragment(calendar, fragment, Calendar.MILLISECOND);
	}

	/**
	 * <p>Returns the number of seconds within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p> 
	 * 
	 * <p>Asking the seconds of any date will only return the number of seconds
	 * of the current minute (resulting in a number between 0 and 59). This 
	 * method will retrieve the number of seconds for any fragment. 
	 * For example, if you want to calculate the number of seconds past today, 
	 * your fragment is Calendar.DATE or Calendar.DAY_OF_YEAR. The result will
	 * be all seconds of the past hour(s) and minutes(s).</p> 
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a SECOND field will return 0.</p> 
	 * 
	 * <p>
	 * <ul>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10
	 *   (equivalent to calendar.get(Calendar.SECOND))</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.MINUTE as fragment will return 10
	 *   (equivalent to calendar.get(Calendar.SECOND))</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 26110
	 *   (7*3600 + 15*60 + 10)</li>
	 *  <li>January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in seconds)</li>
	 * </ul>
	 * </p>
	 * 
	 * @param calendar the calendar to work with, not null
	 * @param fragment the Calendar field part of calendar to calculate 
	 * @return number of seconds within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInSeconds(Calendar calendar, int fragment) {
		return getFragment(calendar, fragment, Calendar.SECOND);
	}

	/**
	 * <p>Returns the number of minutes within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p> 
	 * 
	 * <p>Asking the minutes of any date will only return the number of minutes
	 * of the current hour (resulting in a number between 0 and 59). This 
	 * method will retrieve the number of minutes for any fragment. 
	 * For example, if you want to calculate the number of minutes past this month, 
	 * your fragment is Calendar.MONTH. The result will be all minutes of the 
	 * past day(s) and hour(s).</p> 
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a MINUTE field will return 0.</p> 
	 * 
	 * <p>
	 * <ul>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.HOUR_OF_DAY as fragment will return 15
	 *   (equivalent to calendar.get(Calendar.MINUTES))</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.HOUR_OF_DAY as fragment will return 15
	 *   (equivalent to calendar.get(Calendar.MINUTES))</li>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 15</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 435 (7*60 + 15)</li>
	 *  <li>January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in minutes)</li>
	 * </ul>
	 * </p>
	 * 
	 * @param calendar the calendar to work with, not null
	 * @param fragment the Calendar field part of calendar to calculate 
	 * @return number of minutes within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInMinutes(Calendar calendar, int fragment) {
		return getFragment(calendar, fragment, Calendar.MINUTE);
	}

	/**
	 * <p>Returns the number of hours within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p> 
	 * 
	 * <p>Asking the hours of any date will only return the number of hours
	 * of the current day (resulting in a number between 0 and 23). This 
	 * method will retrieve the number of hours for any fragment. 
	 * For example, if you want to calculate the number of hours past this month, 
	 * your fragment is Calendar.MONTH. The result will be all hours of the 
	 * past day(s).</p> 
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a HOUR field will return 0.</p> 
	 *  
	 * <p>
	 * <ul>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 7
	 *   (equivalent to calendar.get(Calendar.HOUR_OF_DAY))</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.DAY_OF_YEAR as fragment will return 7
	 *   (equivalent to calendar.get(Calendar.HOUR_OF_DAY))</li>
	 *  <li>January 1, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 7</li>
	 *  <li>January 6, 2008 7:15:10.538 with Calendar.MONTH as fragment will return 127 (5*24 + 7)</li>
	 *  <li>January 16, 2008 7:15:10.538 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in hours)</li>
	 * </ul>
	 * </p>
	 *  
	 * @param calendar the calendar to work with, not null
	 * @param fragment the Calendar field part of calendar to calculate 
	 * @return number of hours within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInHours(Calendar calendar, int fragment) {
		return getFragment(calendar, fragment, Calendar.HOUR_OF_DAY);
	}

	/**
	 * <p>Returns the number of days within the 
	 * fragment. All datefields greater than the fragment will be ignored.</p> 
	 * 
	 * <p>Asking the days of any date will only return the number of days
	 * of the current month (resulting in a number between 1 and 31). This 
	 * method will retrieve the number of days for any fragment. 
	 * For example, if you want to calculate the number of days past this year, 
	 * your fragment is Calendar.YEAR. The result will be all days of the 
	 * past month(s).</p> 
	 * 
	 * <p>Valid fragments are: Calendar.YEAR, Calendar.MONTH, both 
	 * Calendar.DAY_OF_YEAR and Calendar.DATE, Calendar.HOUR_OF_DAY, 
	 * Calendar.MINUTE, Calendar.SECOND and Calendar.MILLISECOND
	 * A fragment less than or equal to a DAY field will return 0.</p> 
	 * 
	 * <p>
	 * <ul>
	 *  <li>January 28, 2008 with Calendar.MONTH as fragment will return 28
	 *   (equivalent to calendar.get(Calendar.DAY_OF_MONTH))</li>
	 *  <li>February 28, 2008 with Calendar.MONTH as fragment will return 28
	 *   (equivalent to calendar.get(Calendar.DAY_OF_MONTH))</li>
	 *  <li>January 28, 2008 with Calendar.YEAR as fragment will return 28
	 *   (equivalent to calendar.get(Calendar.DAY_OF_YEAR))</li>
	 *  <li>February 28, 2008 with Calendar.YEAR as fragment will return 59
	 *   (equivalent to calendar.get(Calendar.DAY_OF_YEAR))</li>
	 *  <li>January 28, 2008 with Calendar.MILLISECOND as fragment will return 0
	 *   (a millisecond cannot be split in days)</li>
	 * </ul>
	 * </p>
	 * 
	 * @param calendar the calendar to work with, not null
	 * @param fragment the Calendar field part of calendar to calculate 
	 * @return number of days within the fragment of date
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	public static long getFragmentInDays(Calendar calendar, int fragment) {
		return getFragment(calendar, fragment, Calendar.DAY_OF_YEAR);
	}

	/**
	 * Date-version for fragment-calculation in any unit
	 * 
	 * @param date the date to work with, not null
	 * @param fragment the Calendar field part of date to calculate 
	 * @param unit Calendar field defining the unit
	 * @return number of units within the fragment of the date
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	private static long getFragment(Date date, int fragment, int unit) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return getFragment(calendar, fragment, unit);
	}

	/**
	 * Calendar-version for fragment-calculation in any unit
	 * 
	 * @param calendar the calendar to work with, not null
	 * @param fragment the Calendar field part of calendar to calculate 
	 * @param unit Calendar field defining the unit
	 * @return number of units within the fragment of the calendar
	 * @throws IllegalArgumentException if the date is <code>null</code> or 
	 * fragment is not supported
	 * @since 2.4
	 */
	private static long getFragment(Calendar calendar, int fragment, int unit) {
		if (calendar == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		long millisPerUnit = getMillisPerUnit(unit);
		long result = 0;

		// Fragments bigger than a day require a breakdown to days
		switch (fragment) {
		case Calendar.YEAR:
			result += (calendar.get(Calendar.DAY_OF_YEAR) * MILLIS_PER_DAY) / millisPerUnit;
			break;
		case Calendar.MONTH:
			result += (calendar.get(Calendar.DAY_OF_MONTH) * MILLIS_PER_DAY) / millisPerUnit;
			break;
		}

		switch (fragment) {
		// Number of days already calculated for these cases
		case Calendar.YEAR:
		case Calendar.MONTH:

			// The rest of the valid cases
		case Calendar.DAY_OF_YEAR:
		case Calendar.DATE:
			result += (calendar.get(Calendar.HOUR_OF_DAY) * MILLIS_PER_HOUR) / millisPerUnit;
		case Calendar.HOUR_OF_DAY:
			result += (calendar.get(Calendar.MINUTE) * MILLIS_PER_MINUTE) / millisPerUnit;
		case Calendar.MINUTE:
			result += (calendar.get(Calendar.SECOND) * MILLIS_PER_SECOND) / millisPerUnit;
		case Calendar.SECOND:
			result += (calendar.get(Calendar.MILLISECOND) * 1) / millisPerUnit;
			break;
		case Calendar.MILLISECOND:
			break;//never useful
		default:
			throw new IllegalArgumentException("The fragment " + fragment + " is not supported");
		}
		return result;
	}

	/**
	 * Returns the number of millis of a datefield, if this is a constant value
	 * 
	 * @param unit A Calendar field which is a valid unit for a fragment
	 * @return number of millis
	 * @throws IllegalArgumentException if date can't be represented in millisenconds
	 * @since 2.4 
	 */
	private static long getMillisPerUnit(int unit) {
		long result = Long.MAX_VALUE;
		switch (unit) {
		case Calendar.DAY_OF_YEAR:
		case Calendar.DATE:
			result = MILLIS_PER_DAY;
			break;
		case Calendar.HOUR_OF_DAY:
			result = MILLIS_PER_HOUR;
			break;
		case Calendar.MINUTE:
			result = MILLIS_PER_MINUTE;
			break;
		case Calendar.SECOND:
			result = MILLIS_PER_SECOND;
			break;
		case Calendar.MILLISECOND:
			result = 1;
			break;
		default:
			throw new IllegalArgumentException("The unit " + unit + " cannot be represented is milleseconds");
		}
		return result;
	}

	/**
	 * <p>Date iterator.</p>
	 */
	static class DateIterator implements Iterator {
		private final Calendar endFinal;
		private final Calendar spot;

		/**
		 * Constructs a DateIterator that ranges from one date to another. 
		 *
		 * @param startFinal start date (inclusive)
		 * @param endFinal end date (not inclusive)
		 */
		DateIterator(Calendar startFinal, Calendar endFinal) {
			super();
			this.endFinal = endFinal;
			spot = startFinal;
			spot.add(Calendar.DATE, -1);
		}

		/**
		 * Has the iterator not reached the end date yet?
		 *
		 * @return <code>true</code> if the iterator has yet to reach the end date
		 */
		public boolean hasNext() {
			return spot.before(endFinal);
		}

		/**
		 * Return the next calendar in the iteration
		 *
		 * @return Object calendar for the next date
		 */
		public Object next() {
			if (spot.equals(endFinal)) {
				throw new NoSuchElementException();
			}
			spot.add(Calendar.DATE, 1);
			return spot.clone();
		}

		/**
		 * Always throws UnsupportedOperationException.
		 * 
		 * @throws UnsupportedOperationException
		 * @see java.util.Iterator#remove()
		 */
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	/**
	 * 获取当前操作系统的日期
	 * 
	 * @return Date
	 */
	public static java.sql.Date getSqlDate() {
		try {
			return new java.sql.Date((new java.util.Date()).getTime());
		} catch (Exception e) {
			log.error(e.getMessage());
		}
		return null;
	}//System.out.println(getSqlDate());

	/**
	 * 计算两个日期之间相差的天数
	 * 
	 * @param date1
	 * @param date2
	 */
	public static int diffDate(Date date1, Date date2) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date1);
		Calendar calendar2 = Calendar.getInstance();
		calendar.setTime(date2);

		return diffDate(calendar, calendar2);
	}

	public static int diffDate(Calendar d1, Calendar d2) {
		if (d1.after(d2)) {
			Calendar swap = d1;
			d1 = d2;
			d2 = swap;
		}
		int days = d2.get(Calendar.DAY_OF_YEAR) - d1.get(Calendar.DAY_OF_YEAR);
		int y2 = d2.get(Calendar.YEAR);
		if (d1.get(Calendar.YEAR) != y2) {
			d1 = (Calendar) d1.clone();
			do {
				days += d1.getActualMaximum(Calendar.DAY_OF_YEAR);// 得到当年的实际天数
				d1.add(Calendar.YEAR, 1);
			} while (d1.get(Calendar.YEAR) != y2);
		}
		return days;
	}

	/**
	 * * Get the previous time, from how many days to now. * * 得到当前日期之前的时间
	 * 
	 * @param days
	 *            How many days. *
	 * @return The new previous time.
	 */
	public static long previous(int days) {
		return System.currentTimeMillis() - days * 3600000L * 24L;
	}

	//System.out.println(new Date(previous(10)).toLocaleString());

	/**
	 * 返回年份
	 * 
	 * @param date
	 *            日期
	 * @return 返回年份
	 */
	public static int getYear(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.YEAR);
	}

	/**
	 * 返回月份
	 * 
	 * @param date
	 *            日期
	 * @return 返回月份
	 */
	/*   public static int getMonth(Date date)
	   {
	       Calendar c = Calendar.getInstance();
	       c.setTime(date);
	       return c.get(Calendar.MONTH) + 1;
	   }*/
	/** 
	 * 获取日期中的月 
	 * @param date 日期 
	 * @return 返回给定日期的月份
	 */
	public static String getMonth(Date date) {
		//这个比上面的性能好
		DateFormat f_month = new SimpleDateFormat("MM");
		return f_month.format(date).toString();
	}

	/**
	 * 返回日份
	 * 
	 * @param date
	 *            日期
	 * @return 返回日份
	 */
	public static int getDay(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 返回小时
	 * 
	 * @param date
	 *            日期
	 * @return 返回小时
	 */
	public static int getHour(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.HOUR_OF_DAY);
	}

	/**
	 * 返回分钟
	 * 
	 * @param date
	 *            日期
	 * @return 返回分钟
	 */
	public static int getMinute(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.MINUTE);
	}

	/** 
	 * 获取日期中的时间 
	 * @param date 日期 
	 * @return 时间 
	 */
	public static String getTime(Date date) {
		DateFormat f_time = new SimpleDateFormat("HH时mm分 ss秒");
		return f_time.format(date).toString();
	} //        System.out.println("---------"+getTime(date)); 

	/**
	 * 返回秒钟
	 * 
	 * @param date
	 *            日期
	 * @return 返回秒钟
	 */
	public static int getSecond(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.SECOND);
	}//System.out.println(getSecond(date));

	//-------------------------------月份---------------------------------------------------------
	/**
	 * 获取给定日期对象月份
	 *
	 * @param date
	 * @return
	 */
	public static int getDayInMonth(final Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.MONTH) + 1;
	}//System.out.println(getDayInMonth(vTodayCal.getTime()));

	/**
	 * 获取该月的最后一天
	 * @param date
	 * @return
	 */
	public static Date getMonthEnd(Date date) {
		Calendar clar = Calendar.getInstance();
		clar.setTime(date);
		clar.set(Calendar.YEAR, clar.get(Calendar.YEAR));
		clar.set(Calendar.DAY_OF_MONTH, clar.getActualMaximum(Calendar.DATE));//该月的最后一天
		//clar.set(Calendar.DAY_OF_MONTH, clar.getActualMinimum(Calendar.DATE));//该月的头一天
		return clar.getTime();
	}//System.out.println(getMonthEnd(date));

	/**
	 * 获取指定日期所在月份的第一天，时间清零
	 *
	 * @param date 指定日期
	 * @return
	 */
	public static Date getFirstDayOfMonth(Date date) {
		if (date == null) {
			return date;
		}

		Calendar calendar = converDateToCalendar(date);
		calendar.set(Calendar.DATE, 1);

		return truncateTime(calendar.getTime());
	}//System.out.println(getFirstDayOfMonth(date));

	/**
	 * 取上月1号
	 * @return
	 */
	public static String getFirstDayOfLastMonth() {
		GregorianCalendar gCalendar = new GregorianCalendar();
		gCalendar.set(Calendar.DAY_OF_MONTH, 1);
		gCalendar.add(Calendar.MONTH, -1);
		return DateFormatUtils.formatDateToISOString(gCalendar.getTime());
	}//System.out.println("上月第一天"+getFirstDayOfLastMonth());

	public static Date getMonthBegin(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 1, 0, 0, 0);
		return cal.getTime();
	}

	/**
	 * 得到某年某月的第一天
	 * @param year
	 * @param month
	 * @return
	 */
	public static Date getFirstDayOfMonth(int year, int month) {
		month = month - 1;
		Calendar c = Calendar.getInstance();
		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, month);
		c.set(Calendar.DAY_OF_MONTH, c.getActualMinimum(Calendar.DATE));//该月的头一天
		c.set(Calendar.HOUR_OF_DAY, c.getMinimum(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, c.getMinimum(Calendar.MINUTE));
		c.set(Calendar.SECOND, c.getMinimum(Calendar.SECOND));
		c.set(Calendar.MILLISECOND, c.getMinimum(Calendar.MILLISECOND));
		return c.getTime();

	}//System.out.println(getFirstDayOfMonth(2009,6));

	/**
	 * 提到某年某月的最后一天
	 * @param year
	 * @param month
	 * @return
	 */
	public static Date getLastDayOfMonth(int year, int month) {
		month = month - 1;
		Calendar c = Calendar.getInstance();
		c.set(Calendar.YEAR, year);
		c.set(Calendar.MONTH, month);
		int day = c.getActualMaximum(c.DAY_OF_MONTH);
		c.set(Calendar.DAY_OF_MONTH, day);
		return c.getTime();
	}

	/**返回今天是本月的第几天**/
	public static int dayOfMonthOfToday() {
		GregorianCalendar vTodayCal = new GregorianCalendar();
		return vTodayCal.get(Calendar.DAY_OF_MONTH);
	}//System.out.println(dayOfMonthOfToday())

	//-------------------------------周---------------------------------------------------------
	/**
	 * 计算某一天是一年中的第几个星期
	 * @param date
	 * @return
	 */
	public static int getWeekOfYear(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.clear();
		cal.setTime(date);
		/*	cal.set(Calendar.YEAR,2006);
			cal.set(Calendar.MONTH,8);
			cal.set(Calendar.DAY_OF_MONTH,3);*/
		return cal.get(Calendar.WEEK_OF_YEAR);
	}

	/** 
	 * 获取日期中的星期 
	 * @param date 日期 
	 * @return <tt>ep:星期三</tt>
	 */
	public static String getWeek(Date date) {
		return DateFormatUtils.WEEK_FORMAT.format(date).toString();
	} //System.out.println("---------"+getWeek(date)); 

	/**
	*
	* 获取给定日期对象是星期几
	*
	* @param date
	*            日期对象
	* @return 星期几
	*/
	public static int getDayInWeek(final Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.DAY_OF_WEEK) - 1;
	}//System.out.println(getDayInWeek(vTodayCal.getTime()));

	/**
	 * 根据阿拉伯数字返回中文英文名称
	 *
	 * @param weekNum 星期的阿拉伯数字
	 * @return 中文的星期名称
	 */
	public static String getCnWeek(int weekNum) {
		String[] weekStr = { "星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		return weekStr[weekNum];
	}

	/**
	 * 根据阿拉伯数字返回英文星期名称
	 *
	 * @param weekNum 星期的阿拉伯数字
	 * @return 英文的星期名称
	 */
	public static String getEnWeek(int weekNum) {
		String[] weekStr = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "SaturDay" };
		return weekStr[weekNum];
	}

	/**
	 * 取得当前日期所在周的第一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfWeek(Date date) {
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek()); // Monday
		return c.getTime();
	}

	public static Date nMonthsAgo(Integer n, Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) - n);
		return cal.getTime();
	}

	public static Date nDaysAfter(int n, Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) + n);
		return cal.getTime();
	}

	public static Date nDaysAgo(Integer n, Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH) - n);
		return cal.getTime();
	}

	/**
	 * 根据日期判断是星期几
	 */
	public static String getWeekDay(String DateStr) {

		if (DateStr == null)
			return "";
		Date d = null;
		String weekDay = "";
		try {
			d = DateFormatUtils.parseFromFormats(DateStr);
			weekDay = DateFormatUtils.WEEK_FORMAT.format(d);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return weekDay;
	}//System.out.println(getWeekDay("2009/06/01"));

	/**
	 * 取得当前日期所在周的最后一天
	 * 
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfWeek(Date date) {
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6); // Sunday
		return c.getTime();
	}

	/**
	 * <p>获得指定格式的时间一周时间,按顺序从周一到周日</p>
	 * @param dateFormatStr
	 * @return 一周时间(中国人习惯)
	 */
	@SuppressWarnings("static-access")
	public static String[] getWeekOfDayChina(String dateFormatStr) {
		String[] arr = new String[7];
		Date date = null;
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.SIMPLIFIED_CHINESE);
		sdf.applyPattern(dateFormatStr);
		for (int i = 1, k = 0; i < 8; i++, k++) {
			calendar.set(Calendar.DAY_OF_WEEK, i);
			if (k > 0) {
				date = calendar.getTime();
				String timeStr = sdf.format(date);
				arr[i - 2] = timeStr;
				calendar.setTime(date);
			}

		}
		calendar.add(Calendar.DATE, 1);
		date = calendar.getTime();
		String timeStr = sdf.format(date);
		arr[6] = timeStr;
		return arr;
	}//System.out.println(Arrays.toString(getWeekOfDayChina("yyyy-MM-dd HH:mm")));

	//-------------------------DAY------------------------------------------------

	/**
	 * 获取给定日期对象日
	 *
	 * @param date
	 * @return
	 */
	public static int getDayInDay(final Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.DATE);
	}//System.out.println(getDayInDay(date));

	/**
	 * 取得当前时间
	 * @return <tt>HH:mm:ss</tt>
	 */
	public static String getCurrTime() {
		return DateFormatUtils.TIME_FORMAT.format(Calendar.getInstance());
	}//System.out.println(getCurrTime());

	/**
	 * 获取当前时间
	 *
	 * @return 当前时间
	 */
	public static Date getCurrentDate() {
		return new Date(System.currentTimeMillis());
	}

	/**
	 * 按指定格式获取当前时间字符串
	 *
	 * @param formatStr 日期格式
	 * @return 时间字符串
	 */
	public static String getCurrentDateStr(String formatStr) {
		return DateFormatUtils.format(getCurrentDate(), formatStr);
	}

	/**
	 * <p>返回指定格式的第n天后的时间串</p>
	 * @param date
	 * @param n
	 * @param dateFormatStr
	 * @return n天后的时间串
	 */
	public static String afterNDay(Date date, int n, String dateFormatStr) {
		Calendar c = Calendar.getInstance();
		DateFormat df = new SimpleDateFormat(dateFormatStr);
		c.setTime(date);
		c.add(Calendar.DATE, n);
		Date d = c.getTime();
		String s = df.format(d);
		return s;
	}

	/**
	 * <p>返回指定格式的第n天后的时间串集合</p>
	 * @param date
	 * @param n
	 * @param dateFormatStr
	 * @return n天后的时间串
	 */
	public static String[] getAfterNDay(Date date, int n, String dateFormatStr) {
		Calendar c = Calendar.getInstance();
		String[] st = new String[n];
		DateFormat df = new SimpleDateFormat(dateFormatStr);
		for (int i = 0; i < n; i++) {
			c.setTime(date);
			c.add(Calendar.DATE, i);
			Date d = c.getTime();
			String s = df.format(d);
			st[i] = s;
		}

		return st;
	}//System.out.println(Arrays.toString(getAfterNDay(new Date(), 3, "yyyy-MM-dd")));

	/**
	 * 由于Date类型的toGMTString已经不推荐使用，所以需要自己写将日期转为GMT格式的方法
	 * @param date
	 * @return
	 */
	public static final String toGMT(Date date) {
		Locale aLocale = Locale.US;
		DateFormat fmt = new SimpleDateFormat("EEE,d MMM yyyy hh:mm:ss z", new DateFormatSymbols(aLocale));
		fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
		return fmt.format(date);
	} // System.out.println(toGMT(new Date()));

	/**
	 * Returns a Date set to the first possible millisecond of the day, just
	 * after midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static Date getStartOfDay(Date day) {
		return getStartOfDay(day, Calendar.getInstance());
	}//System.out.println(getStartOfDay(date));

	public static String getBeginDate(Date day) {
		return DateFormatUtils.DATETIME_FORMAT.format(getStartOfDay(day));
	}//System.out.println(getBeginDate(date));

	/**
	 * Returns a Date set to the first possible millisecond of the day, just
	 * after midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static Date getStartOfDay(Date day, Calendar cal) {
		if (day == null)
			day = new Date();
		cal.setTime(day);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE));
		cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
		return cal.getTime();
	}//System.out.println(getStartOfDay(date));

	public static Date getStartOfYesterDay(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, -1);
		return getEndOfDay(calendar.getTime());

	}//System.out.println(getYesterDayBeginDate(date));

	/**
	* Make a date a specified number of days in the future from the
	* provided date.
	*
	* @param date
	*            A benchmark date.
	* @param daysLater
	*            The number of days after the benchmark date you want
	*            to go.
	* @return
	*/
	public static Date makeFutureDate(Date date, int daysLater) {
		Calendar dateOnCalendar = Calendar.getInstance();
		dateOnCalendar.setTime(date);
		dateOnCalendar.add(Calendar.DATE, daysLater);
		return dateOnCalendar.getTime();
	}

	/**
	 * Returns a Date set to the last possible millisecond of the day, just
	 * before midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static Date getEndOfDay(Date day) {
		return getEndOfDay(day, Calendar.getInstance());
	}//System.out.println(getStartOfDay(date));

	public static String getEndDate(Date day) {
		return DateFormatUtils.DATETIME_FORMAT.format(getEndOfDay(day));
	}//System.out.println(getStartOfDay(date));

	/**
	 * 获取一天的结束时间
	 * @param date
	 * @return
	 */
	public static Date getEndOfDay(Date day, Calendar cal) {
		if (day == null)
			day = new Date();
		cal.setTime(day);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE));
		cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
		return cal.getTime();
	}//System.out.println(getStartOfDay(date));

	public static String createDate(Date date, int hour, int min) {

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, hour);
		calendar.set(Calendar.MINUTE, min);
		calendar.set(Calendar.SECOND, min);
		calendar.set(Calendar.MILLISECOND, min);
		return DateFormatUtils.DATETIME_FORMAT.format(calendar.getTime());
	}

	/**     
	 * 将给定时间移动相对月份. 
	 *  @param beginDate 起始日期     
	 * @param amount 数量     
	 * @return 结果日期     */
	public static Date moveMonth(Date beginDate, int amount) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(beginDate);
		cal.add(Calendar.MONTH, amount);
		return cal.getTime();
	}//System.out.println(CURRENTTIME_FORMAT.format(moveMonth(date, 4)));

	//-----------------------------------------------------------------------
	/**
	 * Returns a java.sql.Timestamp equal to the current time
	**/
	public static java.sql.Timestamp now() {
		return new java.sql.Timestamp(new java.util.Date().getTime());
	}

	/**
	 * Returns true if endDate is after startDate or if startDate equals endDate
	 * or if they are the same date.  Returns false if either value is null.
	**/
	public static boolean isValidDateRange(Date startDate, Date endDate) {
		return isValidDateRange(startDate, endDate, true);
	}

	//-----------------------------------------------------------------------
	/**
	 * Returns true if endDate is after startDate or if startDate equals endDate.
	 * Returns false if either value is null.  If equalOK, returns true if the
	 * dates are equal.
	**/
	public static boolean isValidDateRange(Date startDate, Date endDate, boolean equalOK) {
		// false if either value is null
		if (startDate == null || endDate == null) {
			return false;
		}

		if (equalOK) {
			// true if they are equal
			if (startDate.equals(endDate)) {
				return true;
			}
		}

		// true if endDate after startDate
		if (endDate.after(startDate)) {
			return true;
		}

		return false;
	}

	//-----------------------------------------------------------------------

	/**返回本月是本年的第几个月**/
	public static int monthOfYear() {
		GregorianCalendar vTodayCal = new GregorianCalendar();
		return vTodayCal.get(vTodayCal.MONTH) + 1;
	}//System.out.println(monthOfYear());

	/**
	 * 将长日期字符串('yyyy-MM-dd HH:mm:ss'格式)转换为短日期字符串('yyyy-MM-dd'格式)
	 * 
	 * @param calendar
	 * @return
	 */
	public static String getYMDfromYYYYMMdd(String str) {
		if (StringUtils.isNullStr(str))
			return null;
		int pos = str.indexOf(' ');
		if (pos > 0) {
			return str.substring(0, pos);
		}
		return str;
	}//System.out.println(getYMDfromYYYYMMdd("2009-05-04 22:03:34"));

	/**
	* 将一个包含日期/时间的Date类型变量的时间部分除去
	* @param date
	* @return xxxxxx 00:00:00
	*/
	public static Date truncateTime(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}//System.out.println(DateFormatUtils.DATETIME_FORMAT.format(truncateTime(date)));

	/**
	 * 时间清零，只留下原来的日期
	 *
	 * @param date 原Date对象
	 * @return 清零后的日历对象
	 */
	public static Calendar calendarClear(Date date) {
		Calendar calendar = converDateToCalendar(date);

		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);

		return calendar;
	}

	/**
	 * 将Date转换成Calendar
	 *
	 * @param date Date对象
	 * @return Calendar对象
	 */
	public static Calendar converDateToCalendar(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		return calendar;
	}

	/**
	 * 以指定间隔获得起始日期/时间和结束日期/时间之间的所有日期/时间
	 * @param from 其实日期/时间
	 * @param to 结束日期/时间
	 * @param field 指定间隔 Calendar.YEAR, MONTH, DATE, HOUR, MINUTE, SECOND, 等等
	 * @param step 指定步长
	 * @return 包含其中日期/时间的数组,
	 *         在 from != to 的情况下, 返回数组的头必然是 from, 但是尾可能不包括 to;
	 *         如果 from == to, 则返回的数组中只有一个元素 [0] == from == to.
	 * <br>如果 from > to, 返回结果中 from 和 to 将会互换
	 */
	@SuppressWarnings("unchecked")
	public static Date[] getDateRange(Date from, Date to, int field, int step) {
		Calendar calFm = Calendar.getInstance();
		Calendar calTo = Calendar.getInstance();
		if (to.compareTo(from) == 0) {
			Date[] ret = new Date[1];
			ret[0] = from;
			return ret;
		} else if (to.compareTo(from) < 0) {
			calFm.setTime(to);
			calTo.setTime(from);
		} else {
			calFm.setTime(from);
			calTo.setTime(to);
		}
		List dates = new ArrayList();
		for (Calendar pt = calFm; !pt.after(calTo); pt.add(field, step)) {
			dates.add(pt.getTime().clone());
		}
		int size = dates.size();
		Date[] ret = new Date[size];
		for (int i = 0; i < size; i++) {
			ret[i] = (Date) dates.get(i);
		}
		return ret;
	}//已经测试

	/**
	 * 增加字符串日期 返回格式也是格式必须是yyyy-MM-dd
	 * add by shizhongwen
	 * 时间:Feb 3, 2009  4:07:46 PM
	 * @param dateStr 格式必须是yyyy-MM-dd
	 * @param offset 增加,减少天数
	 * @return
	 */
	public static String addStringDate(String dateStr, int offset) {
		if (dateStr == null || dateStr.equals(""))
			return null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date tempDate = new Date();
		Calendar cal = Calendar.getInstance();
		try {
			tempDate = sdf.parse(dateStr);
			cal.setTime(tempDate);
			cal.set(Calendar.DAY_OF_MONTH, (cal.get(Calendar.DAY_OF_MONTH) + offset));
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
		SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
		return sdf1.format(cal.getTime());
	}//System.out.println(addStringDate(dateString,31));

	/**
	 * 把参数日期的时,分,秒清零,返回前一天<br/>
	 * 如:参数为2006-08-22 12:33 那么该方法返回 2006-08-21 00:00
	 *
	 * @param date
	 * @return
	 */
	public static Date getPreDay(Date date) {
		Calendar calendar = calendarClear(date);
		calendar.add(Calendar.DAY_OF_YEAR, -1);
		return calendar.getTime();
	}//System.out.println(getPreDay(date));

	public static String getPreDayStr(Date date) {
		return DateFormatUtils.DATETIME_FORMAT.format(getPreDay(date));
	}//System.out.println(getPreDayStr(date));

	/**
	 * 把参数日期的时,分,秒清零,返回前一天<br/>
	 * 如:参数为2006-08-22 12:33 那么该方法返回 2006-08-23 00:00
	 *
	 * @param date
	 * @return
	 */
	public static Date getNextDay(Date date) {
		Calendar calendar = calendarClear(date);
		calendar.add(Calendar.DAY_OF_YEAR, 1);
		return calendar.getTime();
	}

	/**
	 * 时间对比类型
	 */
	public enum CompareType {
		/**
		 * 用天为单位进行比较
		 */
		Day,

		/**
		 * 用小时为单位进行比较
		 */
		Hours,

		/**
		 * 用分钟为单位进行比较
		 */
		Minute
	}

	/**
	 * 计算量时间之间的差
	 *
	 * @param date 时间
	 * @param compareDate 要对比的时间
	 * @param compareType 对比类型
	 * @return 相差的时间
	 */
	public static String dateCompareTo(Date date, Date compareDate, CompareType compareType) {
		StringBuffer dateStr = new StringBuffer();
		int millisecond = 0;

		// 中文修饰
		switch (compareType) {
		case Minute:
			dateStr.append("分钟");
			millisecond = 60000;
			break;
		case Hours:
			dateStr.append("小时");
			millisecond = 3600000;
			break;
		case Day:
			dateStr.append("天");
			millisecond = 86400000;
			break;
		}

		// 处理Date
		long oldDate = date.getTime();
		long newDate = compareDate.getTime();

		// 计算
		long dispersion = (oldDate - newDate) / millisecond;

		// 处理负数
		if (oldDate - newDate < 0) {
			dispersion *= -1;
			dateStr.append("之前");
		} else {
			dateStr.append("之后");
		}

		return String.valueOf(dispersion) + dateStr.toString();
	}//System.out.println(dateCompareTo(vTodayCal.getTime(),date,CompareType.Hours));

	/**
	 * 日期计算，在指定日期基础上加减指定天数
	 *
	 * @param date 指定日期
	 * @param days 要加减的天数
	 * @return 计算后的日期
	 */
	public static Date addDay(Date date, int days) {
		return computeDate(date, Calendar.DAY_OF_YEAR, days);
	}

	/**
	 * 日期计算，在当前日期基础上加减指定天数
	 *
	 * @param days 要加减的天数
	 * @return 计算后的日期
	 */
	public static Date addDay(int days) {
		return addDay(getCurrentDate(), days);
	}

	/**
	 * 日期计算，在当前日期基础上加减指定小时
	 *
	 * @param date 指定日期
	 * @param hours 要加减的小时
	 * @return 计算后的日期
	 */
	public static Date addHour(Date date, int hours) {
		return computeDate(date, Calendar.HOUR, hours);
	}

	/**
	 * 日期计算，在当前日期基础上加减指定小时
	 *
	 * @param hours 要加减的小时
	 * @return 计算后的日期
	 */
	public static Date addHoure(int hours) {
		return addHour(getCurrentDate(), hours);
	}

	/**
	 * 日期计算，在当前日期基础上加减指定月
	 *
	 * @param date 指定日期
	 * @param hours 要加减的月
	 * @return 计算后的日期
	 */
	public static Date addMonth(Date date, int months) {
		return computeDate(date, Calendar.MONTH, months);
	}

	/**
	 * 日期计算，在当前日期基础上加减指定月
	 *
	 * @param hours 要加减的月
	 * @return 计算后的日期
	 */
	public static Date addMonth(int months) {
		return addMonth(getCurrentDate(), months);
	}

	/**
	*
	* 将某个日期增加指定年数，并返回结果。如果传入负数，则为减。
	*
	* @param date
	*            要操作的日期对象
	* @param ammount
	*            要增加年的数目
	* @return 结果日期对象
	*/
	public static Date addYear(final Date date, final int ammount) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.YEAR, ammount);
		return c.getTime();
	}

	/**
	 * 日期计算，在当前日期基础上加减指定周
	 *
	 * @param date 指定日期
	 * @param hours 要加减的周
	 * @return 计算后的日期
	 */
	public static Date addWeek(Date date, int weeks) {
		return computeDate(date, Calendar.WEEK_OF_YEAR, weeks);
	}

	/**
	 * 日期计算，在当前日期基础上加减指定周
	 *
	 * @param hours 要加减的周
	 * @return 计算后的日期
	 */
	public static Date addWeek(int weeks) {
		return addWeek(getCurrentDate(), weeks);
	}

	/**
	 * 根据日历的规则，为给定的日历字段添加或减去指定的时间量。
	 *
	 * @param date 要计算的日期
	 * @param field 日历字段
	 * @param amount 为字段添加的日期或时间量。
	 * @return
	 */
	public static Date computeDate(Date date, int field, int amount) {
		if (date == null) {
			return date;
		}

		Calendar calendar = converDateToCalendar(date);
		calendar.add(field, amount);

		return calendar.getTime();
	}

	/**
	 * 获取给定日期对象年份
	 *
	 * @param date
	 * @return
	 */
	public static int getDayInYear(final Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.get(Calendar.YEAR);
	}//System.out.println(getDayInYear(vTodayCal.getTime()));

	/**
	 *  Compares two java.util.Date objects and returns a boolean
	 *  based upon beginDate is before endDate
	 *
	 *  @param  beginDate - java.util.Date
	 *  @param  endDate - java.util.Date
	 *  @return boolean
	 */
	public static boolean isBefore(Date beginDate, Date endDate) {
		if (beginDate == null || endDate == null) {
			return false;
		}
		GregorianCalendar calBegin = new GregorianCalendar();
		calBegin.clear();
		calBegin.setTime(beginDate);
		GregorianCalendar calEnd = new GregorianCalendar();
		calEnd.clear();
		calEnd.setTime(endDate);

		return calBegin.before(calEnd);
	}

	public static boolean isBefore(String beginDateStr, String endDateStr, String pattern) {
		FastDateFormat format = FastDateFormat.getInstance(pattern);
		Date beginDate = null;
		Date endDate = null;
		try {
			beginDate = DateFormatUtils.parse(beginDateStr, format);
			endDate = DateFormatUtils.parse(endDateStr, format);
		} catch (ParseException e) {
			return false;
		}

		if (beginDate == null || endDate == null) {
			return false;
		}

		return isBefore(beginDate, endDate);

	}// isBefore()

	/**
	 * 得到今天的最后时间
	 * @return
	 */
	public static Date getEndOfToday() {
		return getEndOfDay(new Date());
	}

	/**
	 * 得到今天的开始时间
	 * @return
	 */
	public static Date getBeginOfToday() {
		return getStartOfDay(new Date());
	}

	/**
	 * 从现在到今天结束的long
	 * @return
	 */
	public static Long getNowToTodayEnd() {
		return getEndOfToday().getTime() - System.currentTimeMillis();
	}

	public static void main(String args[]) {
		Date date = new Date();
		String dateString = "2009-04-05";
		GregorianCalendar vTodayCal = new GregorianCalendar(2009, 8, 14);
		long l = getNowToTodayEnd() / 1000;
		long m = l / 60;
		//System.out.println(m/60);
		System.out.println(compareTime(date, vTodayCal.getTime()));
	}

	public static String buildDateString(Date d) {
		Calendar tmpCalendar = new GregorianCalendar();
		tmpCalendar.setTime(d);
		String r;
		r = (tmpCalendar.get(Calendar.MONTH) + 1) + "/" + tmpCalendar.get(Calendar.DAY_OF_MONTH) + "/"
				+ tmpCalendar.get(Calendar.YEAR);
		r += " " + tmpCalendar.get(Calendar.HOUR_OF_DAY) + ":" + tmpCalendar.get(Calendar.MINUTE);
		return r;
	}
	/**
	 * 返回当前月的最后一秒
	 * @param ar
	 */
	public static Date getLastSecondOfMonth(Date aDate) {
		Calendar cal = Calendar.getInstance();
		
		cal.setTime(new Date());        
    	cal.set(Calendar.DAY_OF_MONTH, 1);  
    	cal.set(Calendar.HOUR_OF_DAY, 23);
    	cal.set(Calendar.MINUTE, 59);
    	cal.set(Calendar.SECOND, 59);
    	cal.roll(Calendar.DAY_OF_MONTH, -1);  
    	
    	return cal.getTime();
	}
	
	/**
	 * 返回当前月的第一秒
	 * @param ar
	 */
	public static Date getFirstSecondOfMonth(Date aDate) {
		Calendar cal = Calendar.getInstance();
		
		cal.setTime(aDate);
		cal.set(Calendar.DATE, 1);  
    	cal.set(Calendar.HOUR_OF_DAY, 0);
    	cal.set(Calendar.MINUTE, 0);
    	cal.set(Calendar.SECOND, 0);
    	
    	return cal.getTime();
	}
	/**
	 * 比较两个时间相隔的天数
	 * @param date
	 * @param date2
	 * @return
	 */
	public static int compareTime(String datestr, String datestr2) {
		Date date=DateFormatUtils.parseFromFormats(datestr);
		Date date2=DateFormatUtils.parseFromFormats(datestr2);
		return compareTime(date, date2);
	}
		/**
		 * 比较两个时间相隔的天数
		 * @param date
		 * @param date2
		 * @return
		 */
		public static int compareTime(Date date, Date date2) {
		Calendar c1 = Calendar.getInstance();
		c1.clear();
		c1.setTime(date);
		int day1 = c1.get(Calendar.DAY_OF_YEAR);
		Calendar c2 = Calendar.getInstance();
		c2.clear();
		c2.setTime(date2);
		int day2 = c2.get(Calendar.DAY_OF_YEAR);
		return Math.abs(day2 - day1);

	}
}
